package LAAMI;

import java.util.*;
import repast.simphony.engine.environment.RunEnvironment;
import repast.simphony.engine.schedule.ScheduledMethod;
import umontreal.iro.lecuyer.probdist.NormalDist;
import umontreal.iro.lecuyer.randvar.NormalGen;
import umontreal.iro.lecuyer.rng.*;
import umontreal.iro.lecuyer.stochprocess.BrownianMotion;
import umontreal.iro.lecuyer.stochprocess.GeometricBrownianMotion;

public class StockMarket {

	private double price;
	private double volatility;
	private double drift;
	public ArrayList<Double> priceList;
	private GeometricBrownianMotion gbm;

	// In the initialization of the stock market entity, we set the initial
	// price as the current price of the stock market, we add this price to the
	// priceList, we set the user-defined drift and volatility and we initialize
	// the instance of the class GeometricBrownianMotion from SSJ library.
	public StockMarket(double initialPrice, double vol, double drift) {
		setPrice(initialPrice);
		priceList = new ArrayList<Double>();
		priceList.add(price);
		setDrift(drift);
		setVolatility(vol);
		int openDays = 365;
		double obsInterval = 0.01;

		// We use SSJ library functions to produce the GeometricBrownianMotion
		// motion
		RandomStream stream = new MRG32k3a();
		NormalDist norm = new NormalDist();
		NormalGen gen = new NormalGen(stream, norm);
		BrownianMotion bm = new BrownianMotion(initialPrice, drift, vol, gen);
		gbm = new GeometricBrownianMotion(initialPrice, drift, vol, bm);
		double[] obsTimes = new double[openDays + 1];
		for (int i = 0; i <= openDays; i++)
			obsTimes[i] = (double) i * obsInterval;
		gbm.setObservationTimes(obsTimes, openDays);
	}

	// In every step it's the first method to be calculated.
	// This method is scheduled to start at the first day of the simulation.
	// We generate a random walk to produce the stock market prices.
	// After a new price is produced, it is set as the new stock price
	// and it is added in the price list.
	@ScheduledMethod(start = 1, interval = 1, priority = 1)
	public void step() {
		int curDay = (int) RunEnvironment.getInstance().getCurrentSchedule()
				.getTickCount();
		if (curDay <= LAAMIBuilder.getExpDay()) {
			gbm.nextObservation();
			setPrice(gbm.getCurrentObservation());
			priceList.add(price);
		}
	}

	/* -------------setters/getters-------------------- */
	public double getPrice() {
		return price;
	}

	public double getDrift() {
		return drift;
	}

	public void setDrift(double d) {
		drift = d;
	}

	public void setPrice(double p) {
		price = p;
	}

	public double getVolatility() {
		return volatility;
	}

	public void setVolatility(double v) {
		volatility = v;
	}
}
